/*
    functions for gridding temperature data

	This doesn't use a grid containing squares defined by latitude and
	longitude, as seems to be the standard, but instead distributes
	grid cells evenly across the globe.  This avoids any bias due
	to unequal land surface areas and also the problem of
	singularities at the poles.

    Copyright (C) 2009-2013 Bob Mottram
    bob@sluggish.dyndns.org

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef GLOBALGRID_H_
#define GLOBALGRID_H_

#include <stdio.h>
#include <vector>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <math.h>
#include "tempdata.h"
#include "gridcell.h"
#include "ghcn.h"

// The number of grid cells is 72x36
// This number is obtained from the GHCN literature as the grid resolution which they use
#define GLOBAL_GRID_DIMENSION 72

using namespace std;

class globalgrid {
private:
	// Checking functions to ensure that the grid is even
	// and that conversions between latitude/longitude and
	// cartesian coordinates are ok.
	static void show_coverage(vector<gridcell> &grid);
	static void check_grid_coverage(vector<gridcell> &grid);
	static void check_latlong_conversion(vector<gridcell> &grid);
	static void check_point_distribution(vector<gridcell> &grid);

	// Evenly distribute points on a sphere
	static void points_on_sphere(int no_of_points,
								 vector<gridcell> &grid);

	// Generates the grid
	static void generate(vector<gridcell> &grid);

public:
	// Converts latitude/longitude to a 3D position within a unit sphere
	static void latlong_to_threed(float longitude, float latitude,
								  float &x, float &y, float &z);

	// Converts a 3D position on a unit sphere to a latitude/longitude
	static void threed_to_latlong(float x, float y, float z,
								  float &longitude, float &latitude);

	// Returns the index of the closest grid cell to the given latitude/longitude
	static int get_closest_grid_cell(float longitude, float latitude,
									 vector<gridcell> &grid);

	// Updates the grid with temperature data
	static void load(vector<tempdata> &data,
					 vector<stationdata> &stations,
					 vector<gridcell> &grid,
					 vector<float> area,
					 vector<long long int> &country_codes,
					 string population_class);

	globalgrid();
	virtual ~globalgrid();
};

#endif /* GLOBALGRID_H_ */
